package com.ant.backstage.controller;

import com.alibaba.fastjson.JSONObject;
import com.ant.backstage.facade.ApiReturn;
import com.ant.backstage.facade.code.ApiReturnCode;
import com.ant.backstage.facade.dto.UserDTO;
import com.ant.backstage.facade.exception.BackstageBusinessException;
import com.ant.backstage.facade.model.Permission;
import com.ant.backstage.facade.model.Role;
import com.ant.backstage.facade.request.power.*;
import com.ant.backstage.facade.response.PageFrontResponse;
import com.ant.backstage.facade.response.vo.PermissionVo;
import com.ant.backstage.facade.response.vo.RoleVo;
import com.ant.backstage.service.PermissionService;
import com.ant.backstage.service.RegisterAndLoginService;
import com.ant.backstage.service.RoleService;
import com.ant.backstage.service.UserService;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import ma.glasnost.orika.MapperFacade;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Api(tags = "权限管理")
@RestController
@RequestMapping("/api/v1/power")
public class PowerController {
    private static Logger logger = LogManager.getLogger(PowerController.class);

    @Resource
    UserService userService;
    @Resource
    RoleService roleService;
    @Resource
    PermissionService permissionService;
    @Resource
    RegisterAndLoginService registerAndLoginService;
    @Resource
    MapperFacade mapperFacade;
    @Resource
    CommonMethod commonMethod;

    @ApiOperation(value = "查所有角色&权限", response = PageFrontResponse.class)
    @RequestMapping(value = "/selectRole", method = RequestMethod.POST)
    public PageFrontResponse selectRole(@RequestBody PageRoleInfoRequest pageRoleInfoRequest, HttpServletRequest request) {
        logger.info("查所有角色&权限 条查 分页PageRoleInfoRequest={}", JSONObject.toJSONString(pageRoleInfoRequest));
        Role role = mapperFacade.map(pageRoleInfoRequest, Role.class);
        String uid = null;
        if (pageRoleInfoRequest.getByUid()) {
            UserDTO userInfoByToken = commonMethod.getUserInfoByToken(request);
            uid = userInfoByToken.getUid();
        }
        PageInfo objectPageInfo = roleService.selectRoles(role, pageRoleInfoRequest.getPageNum(), pageRoleInfoRequest.getPageSize(), uid);
        PageFrontResponse pageFrontResponse = new PageFrontResponse();
        if (objectPageInfo == null) {
            pageFrontResponse.setResultMsg(ApiReturnCode.NO_TERM_DATAS.getMessage());
            pageFrontResponse.setResultCode(ApiReturnCode.NO_TERM_DATAS.getCode());
            return pageFrontResponse;
        }
        List<RoleVo> list = objectPageInfo.getList();
        logger.info("查分页角色信息 出参 objectPageInfo={}", JSONObject.toJSONString(objectPageInfo));
        pageFrontResponse.setData(list).setPageNum(objectPageInfo.getPageNum())
                .setPages(objectPageInfo.getPages()).setPageSize(objectPageInfo.getPageSize())
                .setTotal(objectPageInfo.getTotal());
        pageFrontResponse.setResultMsg(ApiReturnCode.SUCCESSFUL.getMessage());
        pageFrontResponse.setResultCode(ApiReturnCode.SUCCESSFUL.getCode());
        return pageFrontResponse;
    }

    @ApiOperation(value = "查所有权限", response = ApiReturn.class)
    @RequestMapping(value = "/selectPermission", method = RequestMethod.GET)
    public ApiReturn selectPermission(@RequestParam(defaultValue = "false") Boolean allPer, HttpServletRequest request) {
        logger.info("查所有权限");
        ApiReturn apiReturn = new ApiReturn<>();
        List<Permission> lists = permissionService.selectAllPermission();
        if (allPer) {
            UserDTO userPo = commonMethod.getUserInfoByToken(request);
            List<String> permissionsByUid = registerAndLoginService.findPermissionsByUid(userPo.getUid());
            List<String> collect = lists.stream().map(Permission::getPermission).collect(Collectors.toList());
            collect.retainAll(permissionsByUid);
            List<Permission> permissions = new ArrayList<>();
            lists.forEach(p -> {
                collect.forEach(c -> {
                    if (c.equals(p.getPermission())) {
                        permissions.add(p);
                    }
                });
            });
            List<PermissionVo> perlist = mapperFacade.mapAsList(permissions, PermissionVo.class);
            apiReturn.setApiReturnCode(ApiReturnCode.SUCCESSFUL);
            apiReturn.setData(perlist);
            return apiReturn;
        }
        List<PermissionVo> asList = mapperFacade.mapAsList(lists, PermissionVo.class);
        apiReturn.setApiReturnCode(ApiReturnCode.SUCCESSFUL);
        apiReturn.setData(asList);
        return apiReturn;
    }

    @ApiOperation(value = "获取所有角色", response = ApiReturn.class)
    @RequestMapping(value = "/selectAllRole", method = RequestMethod.GET)
    public ApiReturn selectAllRole(@RequestParam(required = false) String uid,
                                   @RequestParam(required = false, defaultValue = "false") boolean ByUid, HttpServletRequest request) {
        logger.info("查所有角色");
        ApiReturn apiReturn = new ApiReturn<>();
        List<Role> lists = null;
        if (StringUtils.isBlank(uid)) {
            lists = roleService.selectAllRole();
        } else {
            lists = roleService.selectRolesByUid(uid);
        }
        if (ByUid) {
            UserDTO userPo = commonMethod.getUserInfoByToken(request);
            List<Role> roles = roleService.selectRolesByUid(userPo.getUid());
            lists.retainAll(roles);
        }
        if (!Optional.ofNullable(lists).isPresent()) {
            apiReturn.setApiReturnCode(ApiReturnCode.SUCCESSFUL);
            apiReturn.setData(null);
            return apiReturn;
        }
        List<RoleVo> asList = mapperFacade.mapAsList(lists, RoleVo.class);
        apiReturn.setApiReturnCode(ApiReturnCode.SUCCESSFUL);
        apiReturn.setData(asList);
        return apiReturn;
    }

    @ApiOperation(value = "新增权限", response = ApiReturn.class)
    @RequestMapping(value = "/addPermission", method = RequestMethod.POST)
    public ApiReturn addPermission(@RequestBody PermissionAddRequest permissionAddRequest, HttpServletRequest request) {
        logger.info("新增权限 入参 permissionAddRequest={}", JSONObject.toJSONString(permissionAddRequest));
        permissionAddRequest.getRoleIds().forEach(item -> {
            //1. 校验所属角色是否存在
            Role role = roleService.selectRolesById(Integer.valueOf(item));
            if (role == null) {
                logger.error("新增权限所属角色不存在,角色ID={},入参permissionAddRequest={}"
                        , item, JSONObject.toJSONString(permissionAddRequest));
                throw new BackstageBusinessException(ApiReturnCode.PARAMS_ERROR.getMessage(), ApiReturnCode.PARAMS_ERROR.getCode());
            }
        });
        UserDTO userPo = commonMethod.getUserInfoByToken(request);
        permissionAddRequest.setCreator(userPo.getUname());
        permissionAddRequest.setEditor(userPo.getUname());
        permissionAddRequest.setCreateTime(new java.util.Date());
        permissionAddRequest.setLastUpdateTime(new Date());
        //2. 新增权限
        ApiReturn apiReturn = permissionService.addPermission(permissionAddRequest);
        return apiReturn;
    }

    @ApiOperation(value = "新增角色", response = ApiReturn.class)
    @RequestMapping(value = "/addRole", method = RequestMethod.POST)
    public ApiReturn addRole(@RequestBody RoleAddRequest roleAddRequest, HttpServletRequest request) {
        logger.info("新增角色 入参 roleAddRequest={}", JSONObject.toJSONString(roleAddRequest));
        List<String> perIds = roleAddRequest.getPerIds();
        perIds.forEach(r -> {
            //1. 校验所属角色是否存在
            Permission per = permissionService.selectPerById(Integer.valueOf(r));
            if (per == null) {
                logger.error("新增角色所属权限不存在,权限ID={},入参 roleAddRequest={}"
                        , r, JSONObject.toJSONString(roleAddRequest));
                throw new BackstageBusinessException(ApiReturnCode.PARAMS_ERROR.getMessage(), ApiReturnCode.PARAMS_ERROR.getCode());
            }
        });
        UserDTO userPo = commonMethod.getUserInfoByToken(request);

        //2. 新增角色
        ApiReturn apiReturn = roleService.addRole(roleAddRequest, userPo);
        return apiReturn;
    }

    @ApiOperation(value = "用户分配角色", response = ApiReturn.class)
    @RequestMapping(value = "/updateUserRoles", method = RequestMethod.POST)
    public ApiReturn updateUserRoles(@RequestBody UpdateUseRolesRequest roleAddRequest, HttpServletRequest request) {
        logger.info("用户分配角色 入参 roleAddRequest={}", JSONObject.toJSONString(roleAddRequest));
        ApiReturn apiReturn = new ApiReturn<>();
        List<String> roleIds = new ArrayList<>();
        if (Optional.ofNullable(roleAddRequest.getNewRoleList()).isPresent()) {
            roleIds.addAll(roleAddRequest.getNewRoleList());
        }
        if (Optional.ofNullable(roleAddRequest.getOldRoleList()).isPresent()) {
            roleIds.addAll(roleAddRequest.getOldRoleList());
        }
        roleIds.stream().distinct().forEach(r -> {
            //1. 校验所属角色是否存在
            Role role = roleService.selectRolesById(Integer.valueOf(r));
            if (role == null) {
                logger.error("变更用户角色,用户新增角色不存在,角色ID={},入参 roleAddRequest={}"
                        , r, JSONObject.toJSONString(roleAddRequest));
                throw new BackstageBusinessException(ApiReturnCode.PARAMS_ERROR.getMessage(), ApiReturnCode.PARAMS_ERROR.getCode());
            }
        });
        //补充参数
        UserDTO userPo = commonMethod.getUserInfoByToken(request);
        //2. 删除用户db中所有的角色，重新新增
        apiReturn = userService.updateUserRoles(roleIds, roleAddRequest, apiReturn, userPo);
        return apiReturn;
    }

    @ApiOperation(value = "修改角色状态", response = ApiReturn.class)
    @RequestMapping(value = "/updateRolesStatus", method = RequestMethod.GET)
    public ApiReturn updateRolesStatus(@RequestParam String rolestatus, @RequestParam String id, HttpServletRequest request) {
        logger.info("修改角色状态 入参 rolestatus={},id={}", rolestatus, id);
        ApiReturn apiReturn = new ApiReturn<>();
        UserDTO userPo = commonMethod.getUserInfoByToken(request);
        apiReturn = roleService.updateRolesStatus(rolestatus, id, apiReturn, userPo);
        return apiReturn;
    }

    @ApiOperation(value = "修改权限状态", response = ApiReturn.class)
    @RequestMapping(value = "/updatePerStatus", method = RequestMethod.GET)
    public ApiReturn updatePerStatus(@RequestParam String statusId, @RequestParam String perId) {
        logger.info("修改权限状态 入参 statusId={},perId={}", statusId, perId);
        ApiReturn apiReturn = new ApiReturn<>();
        permissionService.updatePerStatus(statusId, perId);
        apiReturn.setApiReturnCode(ApiReturnCode.SUCCESSFUL);
        return apiReturn;
    }

    @ApiOperation(value = "移除角色下的权限", response = ApiReturn.class)
    @RequestMapping(value = "/removeRolePermission", method = RequestMethod.GET)
    public ApiReturn removeRolePermission(@RequestParam String roleId, @RequestParam String perId, HttpServletRequest request) {
        logger.info("移除角色下的权限 入参 roleId={},perId={}", roleId, perId);
        UserDTO userPo = commonMethod.getUserInfoByToken(request);
        ApiReturn apiReturn = roleService.removeRolePermission(roleId, perId, userPo);
        apiReturn.setApiReturnCode(ApiReturnCode.SUCCESSFUL);
        return apiReturn;
    }

    @ApiOperation(value = "分配角色权限", response = ApiReturn.class)
    @RequestMapping(value = "/allocationRolePermission", method = RequestMethod.POST)
    public ApiReturn allocationRolePermission(@RequestBody AllocationRoleRequest allocationRoleRequest, HttpServletRequest request) {
        logger.info("分配角色权限 入参 allocationRoleRequest={}", JSONObject.toJSONString(allocationRoleRequest));
        UserDTO userPo = commonMethod.getUserInfoByToken(request);
        ApiReturn apiReturn = roleService.allocationRolePermission(allocationRoleRequest, userPo);
        apiReturn.setApiReturnCode(ApiReturnCode.SUCCESSFUL);
        return apiReturn;
    }

}
